package com.atguigu.tingshu.search.runable;

import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.factory.ScheduleTaskThreadFactory;
import com.atguigu.tingshu.search.service.impl.ItemServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.util.Assert;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Description:  任务（重建布隆）
 */
@Slf4j
public class RebuildDistroBloomFilterRunnable implements Runnable {
    private RedissonClient redissonClient;

    private ItemServiceImpl itemServiceImpl;

    private StringRedisTemplate redisTemplate;

    public RebuildDistroBloomFilterRunnable(RedissonClient redissonClient,
                                            ItemServiceImpl itemServiceImpl,
                                            StringRedisTemplate redisTemplate) {
        this.redissonClient = redissonClient;
        this.itemServiceImpl = itemServiceImpl;
        this.redisTemplate = redisTemplate;
    }

    Logger logger = LoggerFactory.getLogger(this.getClass());
    @Override
    public void run() {
        //创建并初始化新布隆
        RBloomFilter<Object> newBloomFilter = redissonClient.getBloomFilter("albumIdBloomFilter:new");
        newBloomFilter.tryInit(1000000L,0.001);
        Result<List<Long>> albumIds = itemServiceImpl.getAlbumIds();
        List<Long> albumIdsData = albumIds.getData();
        Assert.notNull(albumIdsData, "远程调用获取专辑Id列表失败");
        newBloomFilter.add(albumIdsData);
//        newBloomFilter.add(10000L);
        log.info("新的分布式布隆过滤器数据初始化完毕，且元素个数为：{}", newBloomFilter.count());
        //将这一步使用原子性避免替换失败时布隆过滤器失效
//        redisTemplate.delete("albumIdBloomFilter");
//        redisTemplate.delete("{albumIdBloomFilter}:config");
//        redisTemplate.rename("albumIdBloomFilter:new","albumIdBloomFilter");
        //用重命名将新名字key改为旧名字key
        String script = " redis.call(\"del\",KEYS[1])" + "  redis.call(\"del\",KEYS[2])" + "  redis.call(\"rename\",KEYS[3],KEYS[1])" + "  redis.call(\"rename\",KEYS[4],KEYS[2]) return 1";
        List<String> asList = Arrays.asList("albumIdBloomFilter", "{albumIdBloomFilter}:config", "albumIdBloomFilter:new", "{albumIdBloomFilter:new}:config");
        Long execute = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), asList);
        if (execute == 1) {
            logger.info("新布隆已经上线");
        } else {
            logger.info("老布隆在线，使用的依然是老布隆");
        }
        // 接着让这个任务过一段时间在延迟执行（延时任务+嵌套自己实现定时效果）nacos源码中
//        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
//        scheduledExecutorService.schedule(this,3, TimeUnit.MINUTES);

        ScheduleTaskThreadFactory.getInstance().execute(this, 7L, TimeUnit.DAYS);
    }
}
